﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Net.Http;
using System.Net.WebSockets;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using Core.Common;
using TTSClient.Models;

namespace TTSClient
{
    class TTSUtil
    {
        private static readonly AppSetting appSetting = AppSetting.Current;
        private static string Host => appSetting.ApiUrl;

        public async Task StartAsync(RequestModel model, string fileName, Action success, Action<Exception> exception)
        {
            using var socket = new ClientWebSocket();
            var urlString = $"{Host}?{new AuthorizationModel()}";
            var url = new Uri(urlString);

            try
            {
                socket.Options.KeepAliveInterval = TimeSpan.FromMinutes(2);
                await socket.ConnectAsync(url, CancellationToken.None);
                await Send(socket, model.ToJsonString());
                await Receive(socket, fileName);
                success();
            }
            catch (Exception ex)
            {
                exception(ex);
            }
        }

        private async Task Send(ClientWebSocket socket, string data) => await socket.SendAsync(Encoding.UTF8.GetBytes(data), WebSocketMessageType.Text, true, CancellationToken.None);

        private async Task Receive(ClientWebSocket socket, string fileName)
        {
            WebSocketReceiveResult result = null;
            FileStream fileStream = null;

            do
            {
                try
                {
                    using var memoryStream = new MemoryStream();
                    var buffer = new ArraySegment<byte>(new byte[10240]);
                    do
                    {
                        if (socket.State != WebSocketState.Closed)
                        {
                            result = await socket.ReceiveAsync(buffer, CancellationToken.None);
                            memoryStream.Write(buffer.Array, buffer.Offset, result.Count);
                        }
                    } while (!result.EndOfMessage);

                    if (result.MessageType == WebSocketMessageType.Close)
                        break;

                    memoryStream.Seek(0, SeekOrigin.Begin);
                    using var reader = new StreamReader(memoryStream, Encoding.UTF8);
                    var json = await reader.ReadToEndAsync();
                    var response = json.ToJsonObject<ResponseModel>();
                    if (response != null && response.Code == 0 && response.Message == "success")
                    {
                        var bytes = Convert.FromBase64String(response.Data.Audio);
                        if (bytes.IsNotNullOrEmpty())
                        {
                            if (fileStream == null)
                            {
                                fileStream = File.Create(fileName);
                            }

                            fileStream.Write(bytes);
                        }
                    }
                    else
                    {
                        throw new Exception(response.Code + ": " + response.Message);
                    }
                }
                catch (Exception ex)
                {
                    throw ex;
                }
            } while (socket.State != WebSocketState.Closed && result.MessageType != WebSocketMessageType.Close);

            if (fileStream != null)
            {
                fileStream.Close();
                await fileStream.DisposeAsync();
            }
        }

        public static async Task<ICollection<Language>> GetLanguages()
        {
            var languages = new List<Language>();
            using var httpClient = new HttpClient();

            //获取基础发音人
            var result = await httpClient.GetStringAsync(appSetting.LanguageUrl + "99");
            if (result.IsNotNullOrEmpty())
            {
                var response = result.ToJsonObject<LanguageResponse<Language>>();
                if (response.Data.IsNotNullOrEmpty())
                {
                    foreach (var lang in response.Data)
                    {
                        lang.SetExtension();
                        languages.Add(lang);
                    }
                }
            }

            //获取特色发音人
            result = await httpClient.GetStringAsync(appSetting.LanguageUrl + "0");
            if (result.IsNotNullOrEmpty())
            {
                var response = result.ToJsonObject<LanguageResponse<Language>>();
                if (response.Data.IsNotNullOrEmpty())
                {
                    foreach (var lang in response.Data)
                    {
                        lang.SetExtension();
                        languages.Add(lang);
                    }
                }
            }

            ////获取已添加发音人, 需要先登陆验证, 暂时不做了
            //result = await httpClient.GetStringAsync(appSetting.PaymentLanguageUrl + appSetting.AppId);
            //if (result.IsNotNullOrEmpty())
            //{
            //    var response = result.ToJsonObject<LanguageResponse<PaymentLanguage>>();
            //    if (response.Data.IsNotNullOrEmpty())
            //    {
            //        foreach (var item in response.Data)
            //        {
            //            var lang = languages.FirstOrDefault(x => x.Name == item.Name && x.Code == item.Code);
            //            if (lang != null)
            //            {
            //                lang.Merge(item);
            //            }
            //        }
            //    }
            //}

            return languages;
        }
    }
}
